#include "qrreader.h"

qrReader::qrReader()
{

}

string qrReader::readQrCode(QImage* img)
{
    converter c;
    log.clearLog();
    finderpattern fp;
    fp.setCanvas(&log);
    fp.findFinders(img);
    if (fp.getAngle() != 0)
    {
        adjustImage(fp.getAngle(), img);
        fp.findFinders(img);
    }

    determinePixelProportion(fp.getUpperLeftFinder(), fp.getLowerLeftFinder(), img);
    if (pixelProportion > 0)
    {
        log.addLog("TAMANHO EQUIVALENTE DO PIXEL = " + c.intToString(pixelProportion));
        fp.paintFinders(pixelProportion, img);
        origin.setPoint(fp.getUpperLeftFinder().getRow()-3*pixelProportion, fp.getUpperLeftFinder().getColumn()-3*pixelProportion);
        version v;
        v.setCanvas(&log);
        v.checkVersion(fp.getUpperLeftFinder(), fp.getUpperRightFinder(), fp.getLowerLeftFinder(), pixelProportion, img);
        if (v.getVersionINFO() > 0)
        {
            format f;
            f.setCanvas(&log);

            f.checkFormat(fp.getUpperLeftFinder(), fp.getLowerLeftFinder(), fp.getUpperRightFinder(), pixelProportion, img);
            if (v.getVersionINFO() > 1)
            {
                alignmentpattern ap;
                ap.setCanvas(&log);
                ap.findAlignments(origin, v.getVersionINFO(), pixelProportion, img);
            }
            timmingPattern tp;
            tp.setCanvas(&log);
            tp.findTimming(fp.getUpperLeftFinder(), fp.getUpperRightFinder(), fp.getLowerLeftFinder(), origin, pixelProportion, img);
            if (f.getMaskPattern() >= 0)
            {
                datablock db;
                db.setCanvas(&log);
                vector<int> dataBlocks = db.getDataBlocks(v.getVersionINFO(), f.getMaskPattern(), origin, pixelProportion, img);
                log.addLog("\nNUMERO DE BYTES = " + c.intToString(dataBlocks.size()));
                string data = db.decodeDataBlocks(dataBlocks, v.getVersionINFO());
                if (isDataValid(data))
                    return data;
                else
                    if (v.getVersionINFO() > 6)
                        return "Erro ao decodificar! :(";
            }            
        }
    }
    log.clearLog();
    return "";
}

void qrReader::adjustImage(float angle, QImage *img)
{
    QTransform rotationAdjust;
    rotationAdjust.rotate(angle);

    *img = img->transformed(rotationAdjust);
}

void qrReader::determinePixelProportion(point upperLeft, point lowerLeft, QImage* img)
{
    int distance = abs(upperLeft.getRow()-lowerLeft.getRow());
    int proportion = distance;
    int propAux = 0;
    int middle = upperLeft.getColumn();

    pixel p;
    for (int row = upperLeft.getRow(); row < lowerLeft.getRow(); row++)
    {
        if (p.isPixelBlack(row, middle, img))
            propAux++;
        else
        {
            if (proportion > propAux && propAux != 0)
                proportion = propAux;
            propAux = 0;
        }
    }

    pixelProportion = proportion;
}

bool qrReader::isDataValid(string data)
{
    if (data.length() == 0)
        return false;
    for (int i = 0; i < data.length(); i++)
    {
        int ascValue = data[i];
        if (ascValue > 0 && ascValue != 13 && ascValue != 10 && (ascValue < 32 || ascValue > 126))
            return false;
    }
    return true;
}

canvas qrReader::getCanvas()
{
    return this->log;
}
